﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace QuadRemote.Core
{
    class LogStore
    {
        public Dictionary<Byte, LogValueContainer> values;
        int lastTimeReceived = 0;

        public LogStore()
        {
            values = new Dictionary<Byte, LogValueContainer>();

            Bluetooth.instance().commandParsers[(int)CommandId.CMD_LOG_DATA_REALTIME] = parseIncoming;
        }

        public Boolean isLoaded()
        {
            return values.Count > 0;
        }

        public LogStore(StorageReader fromFile)
        {
            values = new Dictionary<Byte, LogValueContainer>();

            StorageMarker marker = fromFile.readMarker();
            while (marker != StorageMarker.LIST_END)
            {
                String listName = fromFile.ReadString();
                Console.WriteLine("\t" + (int)marker + " => " + listName);
                if (listName == "LogValueContainer")
                {
                    LogValueContainer newContainer = new LogValueContainer(fromFile);
                    if (values.ContainsKey(newContainer.id))
                        Console.WriteLine("Container " + (int)newContainer.id + " - " + newContainer.name + " already exists!");
                    else
                        values.Add(newContainer.id, newContainer);
                }
                else
                    fromFile.ignore(marker);

                marker = fromFile.readMarker();
            }
            Bluetooth.instance().commandParsers[(int)CommandId.CMD_LOG_DATA_REALTIME] = parseIncoming;
        }

        public void resetData()
        {
            foreach (LogValueContainer container in values.Values)
            {
                container.Clear();
                container.minTimestamp = 0;
                container.maxTimestamp = Int32.MaxValue;
            }
        }

        public void save(StorageWriter writer)
        {
            writer.startList("LogStore");
            foreach (LogValueContainer c in values.Values)
            {
                c.save(writer);
            }
            writer.endList();
        }

        public int addDefinition(byte[] param, int offset)
        {
            byte id = param[offset++];
            String name = Tools.bytesToString(param, offset);
            offset += name.Length + 1;

            LogValueContainer c = new LogValueContainer(id, name);
            c.numBytes = param[offset++];
            c.numValues = param[offset++];
            c.isSigned = param[offset++] == 1;
            c.intBits = param[offset++];
            c.floatBits = param[offset++];

            Console.WriteLine("Definition for " + c.name + " (" + (int)id + ") = bytes:" + c.numBytes + " vals:" + c.numValues + " signed:" + (c.isSigned ? 1 : 0) + " int:" + c.intBits +  " float:" + c.floatBits);

            if (values.ContainsKey(id))
            {
                Console.WriteLine("Double definition for " + c.name + " (id=" + (int)id + "); replaced");
                values.Remove(id);
            }
            values.Add(id,c);
            return offset;
        }

        public void parseIncoming(CommandIn args)
        {
            int timestamp = 0;

            byte[] payload = args.packet;
            int p = 0;
            //Console.WriteLine("Incoming log: " + Tools.getHexString(payload));
                    
            while (p < payload.Length)
            {
                byte id = payload[p++];
                if (id == 0)
                {
                    timestamp = Tools.bytesToInt32Rev(payload, p);
                    //Console.WriteLine("- Time: " + timestamp);
                    if (timestamp > lastTimeReceived) lastTimeReceived = timestamp;
                    p += 4;
                }
                else if (id == 1)
                {
                    timestamp += payload[p++];
                }
                else if (id == 2)
                {
                    timestamp++;
                }
                else
                {
                    if (values.ContainsKey(id))
                    {
                        int len = values[id].numBytes;
                        values[id].parseIncoming(timestamp, payload, p);
                        p += len;
                    }
                    else
                    {
                        Console.WriteLine("Received log data without definition (id=" + (int)id + ")");
                        break;
                    }
                }
            }
        }
    }
}
